using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using AandEDLL;
using AandEDLL.DataAccess;
using AandEDLL.Properties;

namespace ASA
{
    public partial class ResultsForm : Form
    {
        private List<Item> m_SearchResults;
        private List<Item> m_SavedItems;
        private List<Category> m_Categories;
        private bool bUpdatingCategories; // used to not make UI changes while category combobox is updating

        private User m_user;
        public User M_User
        {
            get { return m_user; }
        }

        #region Constructors/Initializers
        public ResultsForm()
        {
            InitializeComponent();
            InitResults(null);
        }
        public ResultsForm(AandEDLL.DataAccess.User user)
        {
            InitializeComponent();
            InitResults(user);
        }
        private void InitResults(AandEDLL.DataAccess.User user)
        {
            m_user = user;
            if (m_user.Admin)
                manageUserToolStripMenuItem.Enabled = true;

            UpdateCategoriesComboBox();
            UpdateSavedItems();

            resultsColumnTypes = new ListViewItemComparer.DataType[] { ListViewItemComparer.DataType.String,
                ListViewItemComparer.DataType.String,
                ListViewItemComparer.DataType.Currency,
                ListViewItemComparer.DataType.String,
                ListViewItemComparer.DataType.String};
            itemsColumnTypes = new ListViewItemComparer.DataType[] { ListViewItemComparer.DataType.String,
                ListViewItemComparer.DataType.String,
                ListViewItemComparer.DataType.Currency,
                ListViewItemComparer.DataType.String,
                ListViewItemComparer.DataType.String,
                ListViewItemComparer.DataType.Date};
        }
        #endregion

        #region ListView Sorting Methods
        int resultsSortedColumn = 0;
        bool bResultsAscending = true;
        int itemsSortedColumn = 0;
        bool bItemsAscending = true;

        ListViewItemComparer.DataType[] resultsColumnTypes;
        ListViewItemComparer.DataType[] itemsColumnTypes;

        private void lvSearchResults_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            if (e.Column == resultsSortedColumn)
                bResultsAscending = !bResultsAscending;
            else
            {
                resultsSortedColumn = e.Column;
                bResultsAscending = true;
            }

            lvSearchResults.ListViewItemSorter = new ListViewItemComparer(e.Column, bResultsAscending, resultsColumnTypes[e.Column]);
        }

        private void lvItems_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            if (e.Column == itemsSortedColumn)
                bItemsAscending = !bItemsAscending;
            else
            {
                itemsSortedColumn = e.Column;
                bItemsAscending = true;
            }

            lvItems.ListViewItemSorter = new ListViewItemComparer(e.Column, bItemsAscending, itemsColumnTypes[e.Column]);
        }
        #endregion

        # region ListView Refresh Methods
        public void UpdateSearchResults()
        {
            Font font = new Font(lvSearchResults.Font, FontStyle.Underline);
            if (m_SearchResults != null && m_SearchResults.Count > -1)
            {
                lvSearchResults.Items.Clear();
                ListViewItem lvItem;
                foreach (Item result in m_SearchResults)
                {
                    lvItem = new ListViewItem(result.ItemName);
                    lvItem.UseItemStyleForSubItems = false;
                    lvItem.SubItems.Add(result.Description);
                    lvItem.SubItems.Add(result.Price.ToString("C"));
                    lvItem.SubItems.Add(result.URL, System.Drawing.Color.Blue, lvSearchResults.BackColor, font );
                    lvItem.SubItems.Add(result.Source);
                    lvItem.SubItems.Add(result.SearchDate.ToShortDateString());
                    lvItem.Tag = result;
                    lvSearchResults.Items.Add(lvItem);
                }
            }
        }
        public void UpdateSavedItems()
        {
            if (m_SavedItems != null)
                m_SavedItems.Clear();

            lvItems.Items.Clear();

            if (m_user != null)
            {
                m_SavedItems = AandEDLL.Accessor.GetSavedItems(m_user);
                if (m_SavedItems.Count > 0)
                {
                    // category to filter saved items on
                    int filteredCategoryID = (int)cbCategories.SelectedValue;
                    Font font = new Font(lvSearchResults.Font, FontStyle.Underline);

                    foreach (Item result in m_SavedItems)
                    {
                        // Check filter
                        if (filteredCategoryID != -1 && result.CategoryID != filteredCategoryID)
                            continue;

                        ListViewItem item = new ListViewItem(result.ItemName);
                        item.UseItemStyleForSubItems = false;
                        item.SubItems.Add(result.Category);
                        item.SubItems.Add(result.Description);
                        item.SubItems.Add(result.Price.ToString("C"));
                        item.SubItems.Add(result.URL,System.Drawing.Color.Blue,lvItems.BackColor, font);
                        item.SubItems.Add(result.Source);
                        item.SubItems.Add(result.SearchDate.ToShortDateString());
                        item.Tag = result;
                        lvItems.Items.Add(item);
                    }
                }
            }
        }
        private void refreshSavedItems(object sender, EventArgs e)
        {
            UpdateSavedItems();
        }
        # endregion

        #region Search Method

        private void search(String criterion)
        {
            Regex test = new Regex("[^A-Za-z0-9\\-',\"" + @"\s]");
      
            criterion = test.Replace(criterion, "");
            criterion = criterion.Trim();
            tbSearch.Text = criterion;

            lvSearchResults.Items.Clear();

            if (criterion != "")
            {
                try
                {
                    Cursor.Current = Cursors.WaitCursor;
                    ListViewItem item;
                    this.Enabled = false;

                    toolStripStatusLabel.Text = "Searching...";

                    try
                    {
                        m_SearchResults = AandEDLL.ItemSearch.searchForItems(criterion);
                    } catch (Exception ex)
                    {
                        MessageBox.Show(this,"Search for Items failed. Please check and make sure \n" +
                            "you have an internet connection.", "ASA ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }

                    if (m_SearchResults != null)
                    {
                        Font font = new Font(lvSearchResults.Font, FontStyle.Underline);
                        //m_SearchResults.Clear(); //This is only for testing if no results were found
                        if (m_SearchResults.Count > 0)
                        {
                            foreach (Item result in m_SearchResults)
                            {
                                item = new ListViewItem(result.ItemName);
                                item.UseItemStyleForSubItems = false;
                                item.SubItems.Add(result.Description);
                                item.SubItems.Add(result.Price.ToString("C"));
                                item.SubItems.Add(result.URL,System.Drawing.Color.Blue,lvSearchResults.BackColor, font);
                                item.SubItems.Add(result.Source);
                                item.Tag = result;
                                lvSearchResults.Items.Add(item);
                            }
                            toolStripStatusLabel.Text = "Found " + m_SearchResults.Count + " results.";
                        } else
                        {
                            if (MessageBox.Show(this, "No items were found. Do you want to save your item manually?",
                                "ASA", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                            {
                                AddItemDialog addItemDialog = new AddItemDialog(this);
                                addItemDialog.txtName.Text = tbSearch.Text;
                                addItemDialog.ShowDialog();
                            }
                            toolStripStatusLabel.Text = "";
                        }
                    } else
                    {
                        toolStripStatusLabel.Text = "Search failed.";
                    }
                } catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "ASA ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                } finally
                {
                    Cursor.Current = Cursors.Default;
                    this.Enabled = true;
                }
            }
        }

        private void btnSearch_Click(object sender, EventArgs e)
        {
            search(tbSearch.Text);
        }
        private void searchToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (lvItems.SelectedItems.Count < 1)
            {
                MessageBox.Show("At least one item must be selected.", "Warning");
                return;
            }
            Item item = new Item();
            if (lvItems.SelectedItems != null)
            {
                if (lvItems.SelectedItems.Count > 1)
                {
                    MessageBox.Show("Please select a single item to base your search.", "More Than One Item Selected");
                } else if (lvItems.SelectedItems.Count == 0)
                {
                    MessageBox.Show("Please select an item to base your search.", "No Item Selected");
                } else if (lvItems.SelectedItems.Count == 1)
                {
                    item = (Item)lvItems.SelectedItems[0].Tag;
                    tbSearch.Text = item.ItemName;
                    search(item.ItemName);
                }
            }
        }

        #endregion

        # region Save Methods

        private void saveSelectedItems(object sender, EventArgs e)
        {
            if (lvSearchResults.SelectedItems.Count < 1)
            {
                MessageBox.Show("At least one item must be selected.", "Warning");
                return;
            }
            Item selectedItem;
            List<Item> selectedItemList = new List<Item>();

            CategoryDialog categoryDialog = new CategoryDialog(true);
            categoryDialog.Title = "Select a Category";
            categoryDialog.Text = "Select a Category";
            Int32 categoryID = -1;
            if (categoryDialog.ShowDialog() == DialogResult.OK)
            {
                categoryID = categoryDialog.SelectedCategory.CategoryID;
            }
            else
            {
                MessageBox.Show(this,"No category was assigned to the saved items.", "ASA",MessageBoxButtons.OK,MessageBoxIcon.Warning);
            }
            //if (categoryDialog.ShowDialog() == DialogResult.OK)
            //{
                UpdateCategoriesComboBox();
                Cursor.Current = Cursors.WaitCursor;
                //for all selected items, added User and add Item to List
                foreach (ListViewItem lvItem in lvSearchResults.SelectedItems)
                {
                    selectedItem = (Item)lvItem.Tag;
                    if (m_SearchResults.Contains(selectedItem))
                    {
                        try
                        {
                            selectedItem.User = M_User;
                            //selectedItem.CategoryID = categoryDialog.SelectedCategory.CategoryID;
                            if(categoryID >= 0)
                                selectedItem.CategoryID = categoryID;
                            selectedItemList.Add(selectedItem);
                        } catch (Exception ex)
                        {
                            MessageBox.Show("Could not get selected save item from list.\n" + ex.Message, "ASA ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }
                    }
                }
            //} else
            //{
                //MessageBox.Show("A Category was not selected. Items were not saved.", "Warning");
            //}
            //Save Items to database, then remove items from search results
            if (selectedItemList.Count > 0)
            {
                if (Accessor.SaveItems(selectedItemList))
                {
                    foreach (Item item in selectedItemList)
                    {
                        m_SearchResults.Remove(item);
                    }
                }
            }
            UpdateSearchResults();
            UpdateSavedItems();
            Cursor.Current = Cursors.Default;
            toolStripStatusLabel.Text = "Ready";
            
        }

        #endregion

        # region Delete Methods

        private void deleteSelectedItems(object sender, EventArgs e)
        {
            Item selectedItem;
            List<Item> selectedItemList = new List<Item>();
            if (lvItems.SelectedItems.Count < 1)
            {
                MessageBox.Show("At least one item must be selected.", "Warning");
                return;
            }
            if (lvItems.SelectedItems.Count == 1)
            {
                selectedItem = (Item)lvItems.SelectedItems[0].Tag;
                if (MessageBox.Show("Are you sure you want to remove the item \"" + selectedItem.ItemName + "\"?", "Confirm Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
                    return;
            } else if (lvItems.SelectedItems.Count > 1)
            {
                if (MessageBox.Show("Are you sure you want to remove " + lvItems.SelectedItems.Count + " saved items?", "Confirm Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
                    return;
            }

            Cursor.Current = Cursors.WaitCursor;
            //for all selected items, add Item to List
            foreach (ListViewItem lvItem in lvItems.SelectedItems)
            {
                selectedItem = (Item)lvItem.Tag;
                if (m_SavedItems.Contains(selectedItem))
                {
                    try
                    {
                        selectedItemList.Add(selectedItem);
                    } catch (Exception ex)
                    {
                        MessageBox.Show("Could not get selected save item from list.\n" + ex.Message, "ASA ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
            //Delete Items from database, then remove items from m_savedItems
            if (selectedItemList.Count > 0)
            {
                if (Accessor.DeleteItems(selectedItemList))
                {
                    foreach (Item item in selectedItemList)
                    {
                        m_SavedItems.Remove(item);
                    }
                }
            }
            UpdateSavedItems();
            Cursor.Current = Cursors.Default;
        }


        # endregion

        #region Select All Methods
        private void selectItems(ListView lv, bool selectAll)
        {
            foreach (ListViewItem item in lv.Items)
            {
                item.Selected = selectAll;
            }
            lv.Focus();
        }

        private void selectAllResults(object sender, EventArgs e)
        {
            selectItems(lvSearchResults, true);
        }

        private void deselectAllResults(object sender, EventArgs e)
        {
            selectItems(lvSearchResults, false);
        }

        private void selectAllSavedItems(object sender, EventArgs e)
        {
            selectItems(lvItems, true);
        }

        private void deselectAllSavedItems(object sender, EventArgs e)
        {
            selectItems(lvItems, false);
        }



        #endregion

        private void UpdateCategoriesComboBox()
        {
            // Don't update saved items during refresh
            bUpdatingCategories = true;

            // Set display and value members
            cbCategories.DisplayMember = "Name";
            cbCategories.ValueMember = "CategoryID";

            // create list of categories
            m_Categories = new List<Category>();

            // Add "[All]" category combobox listItem
            AandEDLL.DataAccess.Category allCategory = new AandEDLL.DataAccess.Category();
            allCategory.CategoryID = -1;
            allCategory.Description = string.Empty;
            allCategory.Name = "[All]";
            allCategory.SavedDate = DateTime.Now;
            m_Categories.Add(allCategory);

            // Add the rest of the categories
            List<AandEDLL.DataAccess.Category> list = AandEDLL.Accessor.getCategories();

            // If there are categories defined, add them
            if (list != null && list.Count > 0)
                m_Categories.AddRange(list);

            // set the comboBox datasource
            cbCategories.DataSource = m_Categories;

            bUpdatingCategories = false;

        }
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        private void adminToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ManageUserDialog m = new ManageUserDialog(m_user);
            m.ShowDialog();
        }
        private void btnClear_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show(this, "Are you sure you want to clear search result items?",
                "ASA", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                lvSearchResults.Items.Clear();
                if (m_SearchResults != null)
                    m_SearchResults.Clear();
                toolStripStatusLabel.Text = "Ready";
            }
        }
        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new AboutDialog().ShowDialog();
        }
        private void tbSearch_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Enter)
            {
                btnSearch_Click(this, null);
                e.Handled = true;
            }
        }
        private void btnVisitPage_Click(object sender, EventArgs e)
        {
            if (lvSearchResults.SelectedItems != null && lvSearchResults.SelectedItems.Count == 1)
            {
                string url = ((Item)lvSearchResults.SelectedItems[0].Tag).URL;
                LaunchWebSite(url);
            }
        }
        private void LaunchWebSite(string url)
        {
            try
            {
                Process p = new Process();
                ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo();
                psi.FileName = url;
                p.StartInfo = psi;
                p.Start();
            } catch (Exception err)
            {
                Debug.WriteLine("LaunchWebSite error -> url: " + url + "\n" + err.Message);
            }
        }
        private void btnAddItem_Click(object sender, EventArgs e)
        {
            new AddItemDialog(this).ShowDialog(this);

            // Categories might have been modified
            UpdateCategoriesComboBox();

            // Update search results as category deletion might have removed some
            //UpdateSearchResults();

            // Update Saved items, since they have categories associated with them
            UpdateSavedItems();
        }
        private void documentationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Help.ShowHelp(this, "appraisal.chm");
        }
        private void changeUserInformationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ChangeUserInfoDialog cuiDlg = new ChangeUserInfoDialog(m_user);
            if (cuiDlg.ShowDialog(this) == DialogResult.OK)
                m_user = cuiDlg.user;
        }
        private void manageCategoriesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new CategoryDialog(false).ShowDialog(this);

            // Categories might have been modified
            UpdateCategoriesComboBox();

            // Update search results as category deletion might have removed some
            // UpdateSearchResults();
            // Update Saved items, since they have categories associated with them
            UpdateSavedItems();
        }
        private void clearToolStripMenuItem_Click(object sender, EventArgs e)
        {
            lvSearchResults.Items.Clear();
            toolStripStatusLabel.Text = "Ready";
        }
        //Function to print out an item to the console
        public void PrintItem(Item item)
        {
            Console.Write("\nItem:\n");
            Console.Write("\n\tItemID: {0}", item.ItemID);
            Console.Write("\n\tItemName: {0}", item.ItemName);
            Console.Write("\n\tDescription: {0}", item.Description);
            Console.Write("\n\tPrice: {0}", item.Price);
            Console.Write("\n\tURL: {0}", item.URL);
            Console.Write("\n\tSourceName: {0}", item.Source);
            Console.Write("\n\tUserName: {0}", item.User.UserName);
            Console.Write("\n\tUserID: {0}", item.User.UserID);
            Console.Write("\n\tSearchDate: {0}\n\n", item.SearchDate);

        }
        private void cbCategories_SelectedValueChanged(object sender, EventArgs e)
        {
            if (!bUpdatingCategories)
                UpdateSavedItems();
        }

        private void changeCategoryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (lvItems.SelectedItems.Count < 1)
            {
                MessageBox.Show("At least one item must be selected.", "Warning");
                return;
            }
            CategoryDialog categoryDialog = new CategoryDialog(true);
            if (categoryDialog.ShowDialog() == DialogResult.OK)
            {
                UpdateCategoriesComboBox();
                try
                {

                    Category selectedCategory = categoryDialog.SelectedCategory;
                    List<Item> selectedItemList = new List<Item>();

                    foreach (ListViewItem selectedListItem in lvItems.SelectedItems)
                    {

                        Item selectedItem = (Item)selectedListItem.Tag;

                        selectedItem.CategoryID = selectedCategory.CategoryID;
                        selectedItemList.Add(selectedItem);
                    }
                    Accessor.UpdateItemCategory(selectedItemList);
                    UpdateSavedItems();
                    MessageBox.Show(this, "The selected items have been added to category " +
                        selectedCategory.Name, "ASA", MessageBoxButtons.OK, MessageBoxIcon.Information);
                } catch (Exception ex)
                {
                    MessageBox.Show(this, ex.Message, "ASA", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

            }

        }

        private void logOffToolStripMenuItem_Click(object sender, EventArgs e)
        {
            logOff();
        }

        private void logOff()
        {
            LogOutDialog logOutDialog = new LogOutDialog();
            if (logOutDialog.ShowDialog() == DialogResult.OK)
            {
                Application.Restart();
            }
        }

        private void lvSearchResults_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            string url = ((Item)lvSearchResults.SelectedItems[0].Tag).URL;
            LaunchWebSite(url);
        }

        private void lvItems_DoubleClick(object sender, EventArgs e)
        {
            string url = ((Item)lvItems.SelectedItems[0].Tag).URL;
            LaunchWebSite(url);
        }

      
    }

}